-// ===================================================================\r
-// \r
-// Copyright (c) 2005, Intel Corp.\r
-// All rights reserved.\r
-//\r
-// Redistribution and use in source and binary forms, with or without \r
-// modification, are permitted provided that the following conditions \r
-// are met:\r
-//\r
-// * Redistributions of source code must retain the above copyright \r
-// notice, this list of conditions and the following disclaimer.\r
-// * Redistributions in binary form must reproduce the above \r
-// copyright notice, this list of conditions and the following \r
-// disclaimer in the documentation and/or other materials provided \r
-// with the distribution.\r
-// * Neither the name of Intel Corporation nor the names of its \r
-// contributors may be used to endorse or promote products derived\r
-// from this software without specific prior written permission.\r
-//\r
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \r
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \r
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS \r
-// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \r
-// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
-// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
-// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR \r
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
-// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, \r
-// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) \r
-// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
-// OF THE POSSIBILITY OF SUCH DAMAGE.\r
-// ===================================================================\r
-// \r
-// vtsp.c\r
-// \r
-// Higher level interface to TCS for use in service.\r
-//\r
-// ==================================================================\r
-\r
-#include <string.h>\r
-#include "tcg.h"\r
-#include "tcs.h"\r
-#include "bsg.h"\r
-#include "log.h"\r
-#include "crypto.h"\r
-#include "vtsp.h"\r
-#include "buffer.h"\r
-\r
-#define RSA_KEY_SIZE 0x0800\r
-\r
-/***********************************************************************************\r
- * GenerateAuth: Generate authorization info to be sent back to application\r
- *\r
- * Parameters: outParamDigestText The concatenation of output parameters to be SHA1ed\r
- * outParamDigestTextSize Size of inParamDigestText\r
- * HMACkey Key to be used for HMACing\r
- * For OIAP use key.authUsage or PersistStore.ownerAuth\r
- * For OSAP use shared secret\r
- * pAuth Authorization information from the application\r
- *\r
- * Return: TPM_SUCCESS Authorization data created\r
- * TPM_AUTHFAIL Invalid (NULL) HMACkey presented for OSAP\r
- *************************************************************************************/\r
-TPM_RESULT GenerateAuth( /*[IN]*/ const BYTE *inParamDigestText,\r
- /*[IN]*/ UINT32 inParamDigestTextSize,\r
- /*[IN]*/ const TPM_SECRET *HMACkey, \r
- /*[IN,OUT]*/ TCS_AUTH *auth) {\r
- \r
- if (inParamDigestText == NULL || auth == NULL) \r
- return (TPM_AUTHFAIL);\r
- else {\r
- \r
- //Generate new OddNonce\r
- Crypto_GetRandom(auth->NonceOdd.nonce, sizeof(TPM_NONCE));\r
- \r
- // Create SHA1 inParamDigest\r
- TPM_DIGEST inParamDigest;\r
- Crypto_SHA1Full(inParamDigestText, inParamDigestTextSize, (BYTE *) &inParamDigest);\r
- \r
- // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).\r
- BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];\r
- \r
- BSG_PackList( hmacText, 4, \r
- BSG_TPM_DIGEST, &inParamDigest,\r
- BSG_TPM_NONCE, &(auth->NonceEven),\r
- BSG_TPM_NONCE, &(auth->NonceOdd), \r
- BSG_TYPE_BOOL, &(auth->fContinueAuthSession) );\r
- \r
- Crypto_HMAC((BYTE *) hmacText, sizeof(hmacText), (BYTE *) HMACkey, sizeof(TPM_DIGEST), (BYTE *) &(auth->HMAC));\r
- \r
- return(TPM_SUCCESS);\r
- \r
- }\r
-}\r
-\r
-/***********************************************************************************\r
- * VerifyAuth: Verify the authdata for a command requiring authorization\r
- *\r
- * Parameters: inParamDigestText The concatenation of parameters to be SHA1ed\r
- * inParamDigestTextSize Size of inParamDigestText\r
- * authDataUsage AuthDataUsage for the Entity being used\r
- * Key->authDataUsage or TPM_AUTH_OWNER\r
- * HMACkey Key to be used for HMACing\r
- * For OIAP use key.authUsage or PersistStore.ownerAuth\r
- * For OSAP use NULL (It will be aquired from the Auth Session)\r
- * If unknown (default), assume OIAP\r
- * sessionAuth A TCS_AUTH info for the session\r
- * pAuth Authorization information from the application\r
- * hContext If specified, on failed Auth, VerifyAuth will\r
- * generate a new OIAP session in place of themselves\r
- * destroyed session.\r
- *\r
- * Return: TPM_SUCCESS Authorization Verified\r
- * TPM_AUTHFAIL Authorization Failed\r
- * TPM_FAIL Failure during SHA1 routines\r
- *************************************************************************************/\r
-TPM_RESULT VerifyAuth( /*[IN]*/ const BYTE *outParamDigestText,\r
- /*[IN]*/ UINT32 outParamDigestTextSize,\r
- /*[IN]*/ const TPM_SECRET *HMACkey, \r
- /*[IN,OUT]*/ TCS_AUTH *auth,\r
- /*[IN]*/ TCS_CONTEXT_HANDLE hContext) {\r
- if (outParamDigestText == NULL || auth == NULL) \r
- return (TPM_AUTHFAIL);\r
- \r
- \r
- // Create SHA1 inParamDigest\r
- TPM_DIGEST outParamDigest;\r
- Crypto_SHA1Full(outParamDigestText, outParamDigestTextSize, (BYTE *) &outParamDigest);\r
- \r
- // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).\r
- TPM_DIGEST hm;\r
- BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];\r
- \r
- BSG_PackList( hmacText, 4, \r
- BSG_TPM_DIGEST, &outParamDigest,\r
- BSG_TPM_NONCE, &(auth->NonceEven),\r
- BSG_TPM_NONCE, &(auth->NonceOdd), \r
- BSG_TYPE_BOOL, &(auth->fContinueAuthSession) );\r
- \r
- Crypto_HMAC((BYTE *) hmacText, sizeof(hmacText),\r
- (BYTE *) HMACkey, sizeof(TPM_DIGEST), (BYTE *) &hm);\r
- \r
- // Compare correct HMAC with provided one.\r
- if (memcmp (&hm, &(auth->HMAC), sizeof(TPM_DIGEST)) == 0) // 0 indicates equality\r
- return (TPM_SUCCESS);\r
- else {\r
- VTSP_OIAP( hContext, auth);\r
- return (TPM_AUTHFAIL);\r
- }\r
-}\r
-\r
-TPM_RESULT VTSP_OIAP(const TCS_CONTEXT_HANDLE hContext,\r
- TCS_AUTH *auth) {\r
- \r
- vtpmloginfo(VTPM_LOG_VTSP, "OIAP.\n");\r
- TPM_RESULT status = TPM_SUCCESS; \r
- TPMTRYRETURN( TCSP_OIAP(hContext,\r
- &auth->AuthHandle,\r
- &auth->NonceEven) );\r
- goto egress;\r
- \r
- abort_egress:\r
- \r
- egress:\r
- \r
- return status;\r
-}\r
-\r
-TPM_RESULT VTSP_OSAP(const TCS_CONTEXT_HANDLE hContext,\r
- const TPM_ENTITY_TYPE entityType,\r
- const UINT32 entityValue,\r
- const TPM_AUTHDATA *usageAuth,\r
- TPM_SECRET *sharedSecret, \r
- TCS_AUTH *auth) {\r
- \r
- vtpmloginfo(VTPM_LOG_VTSP, "OSAP.\n");\r
- TPM_RESULT status = TPM_SUCCESS;\r
- TPM_NONCE nonceEvenOSAP, nonceOddOSAP;\r
- \r
- Crypto_GetRandom((BYTE *) &nonceOddOSAP, sizeof(TPM_NONCE) ); \r
- \r
- TPMTRYRETURN( TCSP_OSAP( hContext,\r
- entityType,\r
- entityValue, \r
- nonceOddOSAP,\r
- &auth->AuthHandle, \r
- &auth->NonceEven, \r
- &nonceEvenOSAP) );\r
- \r
- // Calculating Session Secret\r
- BYTE sharedSecretText[TPM_DIGEST_SIZE * 2];\r
- \r
- BSG_PackList( sharedSecretText, 2,\r
- BSG_TPM_NONCE, &nonceEvenOSAP,\r
- BSG_TPM_NONCE, &nonceOddOSAP);\r
- \r
- Crypto_HMAC(sharedSecretText, sizeof(sharedSecretText), (BYTE *) usageAuth, TPM_DIGEST_SIZE, (BYTE *) sharedSecret); \r
- \r
- goto egress;\r
- \r
- abort_egress:\r
- \r
- egress:\r
- \r
- return status;\r
-}\r
-\r
-\r
-\r
-TPM_RESULT VTSP_ReadPubek( const TCS_CONTEXT_HANDLE hContext,\r
- CRYPTO_INFO *crypto_info) {\r
- \r
- TPM_RESULT status;\r
- TPM_NONCE antiReplay;\r
- TPM_DIGEST checksum;\r
- BYTE *pubEKtext;\r
- UINT32 pubEKtextsize;\r
- \r
- vtpmloginfo(VTPM_LOG_VTSP, "Reading Public EK.\n");\r
- \r
- // GenerateAuth new nonceOdd \r
- Crypto_GetRandom(&antiReplay, sizeof(TPM_NONCE) );\r
- \r
- \r
- TPMTRYRETURN( TCSP_ReadPubek( hContext,\r
- antiReplay,\r
- &pubEKtextsize,\r
- &pubEKtext,\r
- &checksum) );\r
- \r
- \r
- // Extract the remaining output parameters\r
- TPM_PUBKEY pubEK;\r
- \r
- BSG_Unpack(BSG_TPM_PUBKEY, pubEKtext, (BYTE *) &pubEK);\r
- \r
- // Build CryptoInfo for the bindingKey\r
- TPM_RSA_KEY_PARMS rsaKeyParms;\r
- \r
- BSG_Unpack(BSG_TPM_RSA_KEY_PARMS, \r
- pubEK.algorithmParms.parms, \r
- &rsaKeyParms);\r
- \r
- Crypto_RSABuildCryptoInfoPublic(rsaKeyParms.exponentSize, \r
- rsaKeyParms.exponent, \r
- pubEK.pubKey.keyLength, \r
- pubEK.pubKey.key, \r
- crypto_info);\r
- \r
- // Destroy rsaKeyParms\r
- BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms);\r
-\r
- // Set encryption scheme\r
- crypto_info->encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1;\r
- //crypto_info->encScheme = pubEK.algorithmParms.encScheme;\r
- crypto_info->algorithmID = pubEK.algorithmParms.algorithmID;\r
- \r
- goto egress;\r
- \r
- abort_egress:\r
- \r
- egress:\r
- \r
- return status;\r
-}\r
-\r
-TPM_RESULT VTSP_TakeOwnership( const TCS_CONTEXT_HANDLE hContext,\r
- const TPM_AUTHDATA *ownerAuth, \r
- const TPM_AUTHDATA *srkAuth,\r
- CRYPTO_INFO *ek_cryptoInfo,\r
- TCS_AUTH *auth) {\r
- \r
- vtpmloginfo(VTPM_LOG_VTSP, "Taking Ownership of TPM.\n");\r
- \r
- TPM_RESULT status = TPM_SUCCESS;\r
- TPM_COMMAND_CODE command = TPM_ORD_TakeOwnership;\r
- TPM_PROTOCOL_ID proto_id = TPM_PID_OWNER;\r
- BYTE *new_srk;\r
- \r
- BYTE *paramText; // Digest to make Auth.\r
- UINT32 paramTextSize;\r
- \r
- // vars for srkpubkey parameter\r
- TPM_KEY srkPub;\r
- TPM_KEY_PARMS srkKeyInfo = {TPM_ALG_RSA, TPM_ES_RSAESOAEP_SHA1_MGF1, TPM_SS_NONE, 12, 0};\r
- BYTE srkRSAkeyInfo[12] = { 0x00, 0x00, (RSA_KEY_SIZE >> 8), 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};\r
- srkKeyInfo.parms = (BYTE *) &srkRSAkeyInfo;\r
- \r
- struct pack_buf_t srkText;\r
- \r
- // GenerateAuth new nonceOdd \r
- Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );\r
- \r
- //These values are accurate for an enc(AuthData).\r
- struct pack_buf_t encOwnerAuth, encSrkAuth;\r
- \r
- encOwnerAuth.data = (BYTE *)malloc(sizeof(BYTE) * 256);\r
- encSrkAuth.data = (BYTE *)malloc(sizeof(BYTE) * 256);\r
- \r
- if (encOwnerAuth.data == NULL || encSrkAuth.data == NULL) {\r
- vtpmloginfo(VTPM_LOG_VTSP, "Could not malloc encrypted auths.\n");\r
- status = TPM_RESOURCES;\r
- goto abort_egress;\r
- }\r
- \r
- Crypto_RSAEnc(ek_cryptoInfo, sizeof(TPM_SECRET), (BYTE *) ownerAuth, &encOwnerAuth.size, encOwnerAuth.data);\r
- Crypto_RSAEnc(ek_cryptoInfo, sizeof(TPM_SECRET), (BYTE *) srkAuth, &encSrkAuth.size, encSrkAuth.data);\r
- \r
- \r
- // Build srk public key struct\r
- srkPub.ver = TPM_STRUCT_VER_1_1;\r
- srkPub.keyUsage = TPM_KEY_STORAGE;\r
- srkPub.keyFlags = 0x00;\r
- srkPub.authDataUsage = TPM_AUTH_ALWAYS;\r
- memcpy(&srkPub.algorithmParms, &srkKeyInfo, sizeof(TPM_KEY_PARMS));\r
- srkPub.PCRInfoSize = 0;\r
- srkPub.PCRInfo = 0;\r
- srkPub.pubKey.keyLength= 0;\r
- srkPub.encDataSize = 0;\r
- \r
- srkText.data = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);\r
- srkText.size = BSG_Pack(BSG_TPM_KEY, (BYTE *) &srkPub, srkText.data);\r
- \r
- paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);\r
- \r
- paramTextSize = BSG_PackList(paramText, 5,\r
- BSG_TPM_COMMAND_CODE,&command,\r
- BSG_TPM_PROTOCOL_ID, &proto_id,\r
- BSG_TPM_SIZE32_DATA, &encOwnerAuth,\r
- BSG_TPM_SIZE32_DATA, &encSrkAuth,\r
- BSG_TPM_KEY, &srkPub);\r
- \r
- TPMTRYRETURN( GenerateAuth( paramText, paramTextSize, ownerAuth, auth) );\r
- \r
- new_srk = srkText.data;\r
- TPMTRYRETURN( TCSP_TakeOwnership ( hContext,\r
- proto_id,\r
- encOwnerAuth.size, \r
- encOwnerAuth.data,\r
- encSrkAuth.size,\r
- encSrkAuth.data,\r
- &srkText.size,\r
- &new_srk, \r
- auth ) );\r
- \r
- \r
- paramTextSize = BSG_PackList(paramText, 2, \r
- BSG_TPM_RESULT, &status,\r
- BSG_TPM_COMMAND_CODE, &command);\r
- memcpy(paramText + paramTextSize, new_srk, srkText.size);\r
- paramTextSize += srkText.size;\r
- \r
- \r
- TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,\r
- ownerAuth, auth, \r
- hContext) );\r
- \r
- goto egress;\r
- \r
- abort_egress:\r
- \r
- egress:\r
- \r
- free(srkText.data);\r
- free(encSrkAuth.data);\r
- free(encOwnerAuth.data);\r
- free(paramText);\r
- \r
- TCS_FreeMemory(hContext, new_srk);\r
- \r
- return status;\r
-}\r
-\r
-TPM_RESULT VTSP_DisablePubekRead( const TCS_CONTEXT_HANDLE hContext,\r
- const TPM_AUTHDATA *ownerAuth, \r
- TCS_AUTH *auth) {\r
- \r
- vtpmloginfo(VTPM_LOG_VTSP, "Disabling Pubek Read.\n");\r
- \r
- TPM_RESULT status = TPM_SUCCESS;\r
- TPM_COMMAND_CODE command = TPM_ORD_DisablePubekRead;\r
- \r
- BYTE *paramText; // Digest to make Auth.\r
- UINT32 paramTextSize;\r
- \r
- // Generate HMAC \r
- Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );\r
- \r
- paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);\r
- \r
- paramTextSize = BSG_PackList(paramText, 1,\r
- BSG_TPM_COMMAND_CODE, &command);\r
- \r
- TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,\r
- ownerAuth, auth) );\r
- \r
- // Call TCS\r
- TPMTRYRETURN( TCSP_DisablePubekRead ( hContext, // in\r
- auth) );\r
- \r
- // Verify Auth\r
- paramTextSize = BSG_PackList(paramText, 2,\r
- BSG_TPM_RESULT, &status,\r
- BSG_TPM_COMMAND_CODE, &command);\r
- \r
- TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,\r
- ownerAuth, auth, \r
- hContext) );\r
- goto egress;\r
- \r
- abort_egress:\r
- egress:\r
- free(paramText);\r
- return status;\r
-}\r
-\r
-TPM_RESULT VTSP_CreateWrapKey( const TCS_CONTEXT_HANDLE hContext,\r
- const TPM_KEY_USAGE usage,\r
- const TPM_AUTHDATA *newKeyAuth,\r
- const TCS_KEY_HANDLE parentHandle, \r
- const TPM_AUTHDATA *osapSharedSecret,\r
- buffer_t *pubKeyBuf,\r
- TCS_AUTH *auth) {\r
- \r
- int i;\r
- TPM_RESULT status = TPM_SUCCESS;\r
- TPM_COMMAND_CODE command = TPM_ORD_CreateWrapKey;\r
- \r
- vtpmloginfo(VTPM_LOG_VTSP, "Creating new key of type %d.\n", usage);\r
- \r
- // vars for Calculate encUsageAuth\r
- BYTE *paramText; \r
- UINT32 paramTextSize;\r
- \r
- // vars for Calculate encUsageAuth\r
- BYTE XORbuffer[sizeof(TPM_SECRET) + sizeof(TPM_NONCE)];\r
- TPM_DIGEST XORKey1;\r
- UINT32 XORbufferSize;\r
- TPM_SECRET encUsageAuth, encMigrationAuth;\r
- \r
- // vars for Flatten newKey prototype\r
- BYTE *flatKey = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);\r
- UINT32 flatKeySize = TCPA_MAX_BUFFER_LENGTH; \r
- struct pack_buf_t newKeyText;\r
- \r
- // Fill in newKey\r
- TPM_KEY newKey;\r
- \r
- BYTE RSAkeyInfo[12] = { 0x00, 0x00, (RSA_KEY_SIZE >> 8), 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};\r
- newKey.algorithmParms.algorithmID = TPM_ALG_RSA;\r
- newKey.algorithmParms.parms = (BYTE *) &RSAkeyInfo;\r
- newKey.algorithmParms.parmSize = 12;\r
- \r
- switch (usage) {\r
- case TPM_KEY_SIGNING:\r
- vtpmloginfo(VTPM_LOG_VTSP, "Creating Signing Key...\n");\r
- newKey.keyUsage = TPM_KEY_SIGNING;\r
- newKey.algorithmParms.encScheme = TPM_ES_NONE;\r
- newKey.algorithmParms.sigScheme = TPM_SS_RSASSAPKCS1v15_SHA1;\r
- break;\r
- case TPM_KEY_STORAGE:\r
- vtpmloginfo(VTPM_LOG_VTSP, "Creating Storage Key...\n");\r
- newKey.keyUsage = TPM_KEY_STORAGE;\r
- newKey.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1;\r
- newKey.algorithmParms.sigScheme = TPM_SS_NONE;\r
- break;\r
- case TPM_KEY_BIND:\r
- vtpmloginfo(VTPM_LOG_VTSP, "Creating Binding Key...\n");\r
- newKey.keyUsage = TPM_KEY_BIND;\r
- newKey.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1;\r
- newKey.algorithmParms.sigScheme = TPM_SS_NONE;\r
- break;\r
- default:\r
- vtpmloginfo(VTPM_LOG_VTSP, "Cannot create key. Invalid Key Type.\n");\r
- status = TPM_BAD_PARAMETER;\r
- goto abort_egress;\r
- }\r
- \r
- \r
- newKey.ver = TPM_STRUCT_VER_1_1;\r
- \r
- newKey.keyFlags = 0;\r
- newKey.authDataUsage = TPM_AUTH_ALWAYS;\r
- newKey.pubKey.keyLength= 0;\r
- newKey.encDataSize = 0;\r
- newKey.encData = NULL;\r
- \r
- // FIXME: Support PCR bindings\r
- newKey.PCRInfoSize = 0;\r
- newKey.PCRInfo = NULL;\r
- \r
- // Calculate encUsageAuth \r
- XORbufferSize = BSG_PackList( XORbuffer, 2, \r
- BSG_TPM_SECRET, osapSharedSecret,\r
- BSG_TPM_NONCE, &auth->NonceEven);\r
- Crypto_SHA1Full(XORbuffer, XORbufferSize, (BYTE *) &XORKey1);\r
- \r
- // FIXME: No support for migratable keys.\r
- for (i=0; i < TPM_DIGEST_SIZE; i++) \r
- ((BYTE *) &encUsageAuth)[i] = ((BYTE *) &XORKey1)[i] ^ ((BYTE *) newKeyAuth)[i];\r
- \r
- // Flatten newKey prototype\r
- flatKeySize = BSG_Pack(BSG_TPM_KEY, (BYTE *) &newKey, flatKey);\r
- newKeyText.data = flatKey;\r
- newKeyText.size = flatKeySize;\r
- \r
- // GenerateAuth new nonceOdd \r
- Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );\r
- \r
- // Generate HMAC\r
- paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);\r
- \r
- paramTextSize = BSG_PackList(paramText, 3,\r
- BSG_TPM_COMMAND_CODE, &command,\r
- BSG_TPM_AUTHDATA, &encUsageAuth,\r
- BSG_TPM_AUTHDATA, &encMigrationAuth);\r
- memcpy(paramText + paramTextSize, newKeyText.data, newKeyText.size);\r
- paramTextSize += newKeyText.size;\r
- \r
- \r
- TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,\r
- osapSharedSecret, auth) );\r
- \r
- // Call TCS\r
- TPMTRYRETURN( TCSP_CreateWrapKey( hContext, \r
- parentHandle,\r
- encUsageAuth,\r
- encMigrationAuth,\r
- &newKeyText.size,\r
- &newKeyText.data,\r
- auth) );\r
- \r
- // Verify Auth\r
- paramTextSize = BSG_PackList(paramText, 2,\r
- BSG_TPM_RESULT, &status,\r
- BSG_TPM_COMMAND_CODE, &command);\r
- memcpy(paramText + paramTextSize, newKeyText.data, newKeyText.size);\r
- paramTextSize += newKeyText.size;\r
- \r
- TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,\r
- osapSharedSecret, auth, 0) );\r
- \r
- // Unpack/return key structure\r
- TPMTRYRETURN(buffer_init(pubKeyBuf, 0, 0) );\r
- TPMTRYRETURN(buffer_append_raw(pubKeyBuf, newKeyText.size, newKeyText.data) );\r
- \r
- goto egress;\r
- \r
- abort_egress:\r
- \r
- egress:\r
- \r
- free(flatKey);\r
- free(paramText);\r
- TCS_FreeMemory(hContext, newKeyText.data);\r
- \r
- return status;\r
-}\r
-\r
-TPM_RESULT VTSP_LoadKey(const TCS_CONTEXT_HANDLE hContext,\r
- const TCS_KEY_HANDLE hUnwrappingKey,\r
- const buffer_t *rgbWrappedKeyBlob,\r
- const TPM_AUTHDATA *parentAuth,\r
- TPM_HANDLE *newKeyHandle,\r
- TCS_AUTH *auth,\r
- CRYPTO_INFO *cryptoinfo /*= NULL*/) {\r
- \r
- \r
- vtpmloginfo(VTPM_LOG_VTSP, "Loading Key.\n%s","");\r
- \r
- TPM_RESULT status = TPM_SUCCESS;\r
- TPM_COMMAND_CODE command = TPM_ORD_LoadKey;\r
- \r
- BYTE *paramText; // Digest to make Auth.\r
- UINT32 paramTextSize;\r
- \r
- if ((rgbWrappedKeyBlob == NULL) || (parentAuth == NULL) || \r
- (newKeyHandle==NULL) || (auth==NULL)) {\r
- status = TPM_BAD_PARAMETER;\r
- goto abort_egress;\r
- }\r
- \r
- // Generate Extra TCS Parameters\r
- TPM_HANDLE phKeyHMAC;\r
- \r
- // Generate HMAC\r
- Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );\r
- \r
- paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);\r
- \r
- paramTextSize = BSG_PackList(paramText, 1,\r
- BSG_TPM_COMMAND_CODE, &command);\r
- \r
- memcpy(paramText + paramTextSize, rgbWrappedKeyBlob->bytes, buffer_len(rgbWrappedKeyBlob));\r
- paramTextSize += buffer_len(rgbWrappedKeyBlob);\r
- \r
- TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,\r
- parentAuth, auth) );\r
- \r
- // Call TCS\r
- TPMTRYRETURN( TCSP_LoadKeyByBlob( hContext,\r
- hUnwrappingKey,\r
- buffer_len(rgbWrappedKeyBlob),\r
- rgbWrappedKeyBlob->bytes,\r
- auth,\r
- newKeyHandle,\r
- &phKeyHMAC) );\r
- \r
- // Verify Auth\r
- paramTextSize = BSG_PackList(paramText, 3,\r
- BSG_TPM_RESULT, &status,\r
- BSG_TPM_COMMAND_CODE, &command,\r
- BSG_TPM_HANDLE, newKeyHandle);\r
- \r
- TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,\r
- parentAuth, auth, \r
- hContext) );\r
- \r
- // Unpack/return key structure\r
- if (cryptoinfo != NULL) {\r
- TPM_KEY newKey;\r
- \r
- BSG_Unpack(BSG_TPM_KEY, rgbWrappedKeyBlob->bytes , &newKey);\r
- TPM_RSA_KEY_PARMS rsaKeyParms;\r
- \r
- BSG_Unpack(BSG_TPM_RSA_KEY_PARMS, \r
- newKey.algorithmParms.parms, \r
- &rsaKeyParms);\r
- \r
- Crypto_RSABuildCryptoInfoPublic(rsaKeyParms.exponentSize, \r
- rsaKeyParms.exponent, \r
- newKey.pubKey.keyLength, \r
- newKey.pubKey.key, \r
- cryptoinfo);\r
- \r
- // Destroy rsaKeyParms\r
- BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms);\r
- \r
- // Set encryption scheme\r
- cryptoinfo->encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1;\r
- }\r
- \r
- goto egress;\r
- \r
- abort_egress:\r
- \r
- egress:\r
- \r
- free(paramText);\r
- return status;\r
-}\r
-\r
-TPM_RESULT VTSP_Unbind( const TCS_CONTEXT_HANDLE hContext,\r
- const TPM_KEY_HANDLE key_handle,\r
- const buffer_t *bound_data,\r
- const TPM_AUTHDATA *usage_auth,\r
- buffer_t *clear_data,\r
- TCS_AUTH *auth) {\r
- \r
- vtpmloginfo(VTPM_LOG_VTSP, "Unbinding %d bytes of data.\n", buffer_len(bound_data));\r
- \r
- TPM_RESULT status = TPM_SUCCESS;\r
- TPM_COMMAND_CODE command = TPM_ORD_UnBind;\r
- \r
- BYTE *paramText; // Digest to make Auth.\r
- UINT32 paramTextSize;\r
- \r
- // Generate Extra TCS Parameters\r
- struct pack_buf_t clear_data32;\r
- BYTE *clear_data_text;\r
- UINT32 clear_data_size;\r
- \r
- // Generate HMAC \r
- Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );\r
- \r
- struct pack_buf_t bound_data32 = {bound_data->size, bound_data->bytes};\r
- \r
- paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);\r
- \r
- paramTextSize = BSG_PackList(paramText, 2,\r
- BSG_TPM_COMMAND_CODE, &command,\r
- BSG_TPM_SIZE32_DATA, &bound_data32);\r
- \r
- TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,\r
- usage_auth, auth) );\r
- \r
- // Call TCS\r
- TPMTRYRETURN( TCSP_UnBind( hContext,\r
- key_handle,\r
- buffer_len(bound_data),\r
- bound_data->bytes,\r
- auth,\r
- &clear_data_size,\r
- &clear_data_text) );\r
- \r
- \r
- // Verify Auth\r
- clear_data32.size = clear_data_size;\r
- clear_data32.data = clear_data_text;\r
- paramTextSize = BSG_PackList(paramText, 3,\r
- BSG_TPM_RESULT, &status,\r
- BSG_TPM_COMMAND_CODE, &command,\r
- BSG_TPM_SIZE32_DATA, &clear_data32);\r
- \r
- TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,\r
- usage_auth, auth, \r
- hContext) );\r
- \r
- // Unpack/return key structure\r
- TPMTRYRETURN(buffer_init(clear_data, 0, 0));\r
- TPMTRYRETURN(buffer_append_raw (clear_data, clear_data_size, clear_data_text) );\r
- \r
- goto egress;\r
- \r
- abort_egress:\r
- \r
- egress:\r
- \r
- free(paramText);\r
- TCS_FreeMemory(hContext, clear_data_text);\r
- \r
- return status;\r
-}\r
-\r
-TPM_RESULT VTSP_Bind( CRYPTO_INFO *cryptoInfo, \r
- const buffer_t *inData, \r
- buffer_t *outData) \r
-{\r
- vtpmloginfo(VTPM_LOG_VTSP, "Binding %d bytes of data.\n", buffer_len(inData));\r
- TPM_BOUND_DATA boundData;\r
- UINT32 i;\r
- \r
- // Fill boundData's accessory information\r
- boundData.ver = TPM_STRUCT_VER_1_1;\r
- boundData.payload = TPM_PT_BIND;\r
- boundData.payloadData = inData->bytes;\r
- \r
- // Pack boundData before encryption\r
- BYTE* flatBoundData = (BYTE *)malloc(sizeof(BYTE) * \r
- (sizeof(TPM_VERSION) +\r
- sizeof(TPM_PAYLOAD_TYPE) +\r
- buffer_len(inData)));\r
- if (flatBoundData == NULL) {\r
- return TPM_NOSPACE;\r
- }\r
- UINT32 flatBoundDataSize = 0;\r
- flatBoundDataSize = BSG_PackList( flatBoundData, 2, \r
- BSG_TPM_VERSION, &boundData.ver, \r
- BSG_TYPE_BYTE, &boundData.payload);\r
- \r
- memcpy(flatBoundData+flatBoundDataSize, inData->bytes, buffer_len(inData));\r
- flatBoundDataSize += buffer_len(inData);\r
- \r
- BYTE out_tmp[RSA_KEY_SIZE/8]; // RSAEnc does not do blocking, So this is what will come out.\r
- UINT32 out_tmp_size;\r
- \r
- // Encrypt flatBoundData\r
- Crypto_RSAEnc( cryptoInfo, \r
- flatBoundDataSize, \r
- flatBoundData, \r
- &out_tmp_size, \r
- out_tmp);\r
- \r
- if (out_tmp_size > RSA_KEY_SIZE/8) {\r
- // The result of RSAEnc should be a fixed size based on key size.\r
- vtpmlogerror(VTPM_LOG_VTSP, "Enc buffer just overflowed.\n");\r
- }\r
- \r
- buffer_init(outData, 0, NULL);\r
- buffer_append_raw(outData, out_tmp_size, out_tmp);\r
- \r
- vtpmloginfo(VTPM_LOG_TXDATA, "Bind Generated[%d] = 0x", out_tmp_size);\r
- for(i = 0 ; i < out_tmp_size ; i++) {\r
- vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", out_tmp[i]);\r
- }\r
- vtpmloginfomore(VTPM_LOG_TXDATA, "\n");\r
- \r
- // Free flatBoundData\r
- free(flatBoundData);\r
- \r
- return TPM_SUCCESS;\r
-}\r
-\r
-// Function Reaches into unsupported TCS command, beware.\r
-TPM_RESULT VTSP_RawTransmit(const TCS_CONTEXT_HANDLE hContext,\r
- const buffer_t *inbuf,\r
- buffer_t *outbuf ) {\r
- \r
- vtpmloginfo(VTPM_LOG_VTSP, "Passthrough in use.\n");\r
- TPM_RESULT status = TPM_SUCCESS;\r
- \r
- // Generate Extra TCS Parameters\r
- BYTE *resultText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);\r
- UINT32 resultTextSize = TCPA_MAX_BUFFER_LENGTH;\r
- \r
- // Call TCS \r
- TPMTRYRETURN( TCSP_RawTransmitData(buffer_len(inbuf), inbuf->bytes, \r
- &resultTextSize, resultText) );\r
- \r
- // Unpack/return key structure\r
- TPMTRYRETURN(buffer_init (outbuf, resultTextSize, resultText) ); \r
- goto egress;\r
- \r
- abort_egress:\r
- \r
- egress:\r
- TCS_FreeMemory(hContext, resultText);\r
- free(resultText);\r
- return status;\r
-}\r
+// ===================================================================
+//
+// Copyright (c) 2005, Intel Corp.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Intel Corporation nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+// ===================================================================
+//
+// vtsp.c
+//
+// Higher level interface to TCS for use in service.
+//
+// ==================================================================
+
+#include <string.h>
+#include "tcg.h"
+#include "tcs.h"
+#include "bsg.h"
+#include "log.h"
+#include "crypto.h"
+#include "vtsp.h"
+#include "buffer.h"
+
+#define RSA_KEY_SIZE 0x0800
+
+/***********************************************************************************
+ * GenerateAuth: Generate authorization info to be sent back to application
+ *
+ * Parameters: outParamDigestText The concatenation of output parameters to be SHA1ed
+ * outParamDigestTextSize Size of inParamDigestText
+ * HMACkey Key to be used for HMACing
+ * For OIAP use key.authUsage or PersistStore.ownerAuth
+ * For OSAP use shared secret
+ * pAuth Authorization information from the application
+ *
+ * Return: TPM_SUCCESS Authorization data created
+ * TPM_AUTHFAIL Invalid (NULL) HMACkey presented for OSAP
+ *************************************************************************************/
+TPM_RESULT GenerateAuth( /*[IN]*/ const BYTE *inParamDigestText,
+ /*[IN]*/ UINT32 inParamDigestTextSize,
+ /*[IN]*/ const TPM_SECRET *HMACkey,
+ /*[IN,OUT]*/ TCS_AUTH *auth) {
+
+ if (inParamDigestText == NULL || auth == NULL)
+ return (TPM_AUTHFAIL);
+ else {
+
+ //Generate new OddNonce
+ Crypto_GetRandom(auth->NonceOdd.nonce, sizeof(TPM_NONCE));
+
+ // Create SHA1 inParamDigest
+ TPM_DIGEST inParamDigest;
+ Crypto_SHA1Full(inParamDigestText, inParamDigestTextSize, (BYTE *) &inParamDigest);
+
+ // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).
+ BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];
+
+ BSG_PackList( hmacText, 4,
+ BSG_TPM_DIGEST, &inParamDigest,
+ BSG_TPM_NONCE, &(auth->NonceEven),
+ BSG_TPM_NONCE, &(auth->NonceOdd),
+ BSG_TYPE_BOOL, &(auth->fContinueAuthSession) );
+
+ Crypto_HMAC((BYTE *) hmacText, sizeof(hmacText), (BYTE *) HMACkey, sizeof(TPM_DIGEST), (BYTE *) &(auth->HMAC));
+
+ return(TPM_SUCCESS);
+
+ }
+}
+
+/***********************************************************************************
+ * VerifyAuth: Verify the authdata for a command requiring authorization
+ *
+ * Parameters: inParamDigestText The concatenation of parameters to be SHA1ed
+ * inParamDigestTextSize Size of inParamDigestText
+ * authDataUsage AuthDataUsage for the Entity being used
+ * Key->authDataUsage or TPM_AUTH_OWNER
+ * HMACkey Key to be used for HMACing
+ * For OIAP use key.authUsage or PersistStore.ownerAuth
+ * For OSAP use NULL (It will be aquired from the Auth Session)
+ * If unknown (default), assume OIAP
+ * sessionAuth A TCS_AUTH info for the session
+ * pAuth Authorization information from the application
+ * hContext If specified, on failed Auth, VerifyAuth will
+ * generate a new OIAP session in place of themselves
+ * destroyed session.
+ *
+ * Return: TPM_SUCCESS Authorization Verified
+ * TPM_AUTHFAIL Authorization Failed
+ * TPM_FAIL Failure during SHA1 routines
+ *************************************************************************************/
+TPM_RESULT VerifyAuth( /*[IN]*/ const BYTE *outParamDigestText,
+ /*[IN]*/ UINT32 outParamDigestTextSize,
+ /*[IN]*/ const TPM_SECRET *HMACkey,
+ /*[IN,OUT]*/ TCS_AUTH *auth,
+ /*[IN]*/ TCS_CONTEXT_HANDLE hContext) {
+ if (outParamDigestText == NULL || auth == NULL)
+ return (TPM_AUTHFAIL);
+
+
+ // Create SHA1 inParamDigest
+ TPM_DIGEST outParamDigest;
+ Crypto_SHA1Full(outParamDigestText, outParamDigestTextSize, (BYTE *) &outParamDigest);
+
+ // Create HMAC text. (Concat inParamsDigest with inAuthSetupParams).
+ TPM_DIGEST hm;
+ BYTE hmacText[sizeof(TPM_DIGEST) + (2 * sizeof(TPM_NONCE)) + sizeof(BOOL)];
+
+ BSG_PackList( hmacText, 4,
+ BSG_TPM_DIGEST, &outParamDigest,
+ BSG_TPM_NONCE, &(auth->NonceEven),
+ BSG_TPM_NONCE, &(auth->NonceOdd),
+ BSG_TYPE_BOOL, &(auth->fContinueAuthSession) );
+
+ Crypto_HMAC((BYTE *) hmacText, sizeof(hmacText),
+ (BYTE *) HMACkey, sizeof(TPM_DIGEST), (BYTE *) &hm);
+
+ // Compare correct HMAC with provided one.
+ if (memcmp (&hm, &(auth->HMAC), sizeof(TPM_DIGEST)) == 0) // 0 indicates equality
+ return (TPM_SUCCESS);
+ else {
+ VTSP_OIAP( hContext, auth);
+ return (TPM_AUTHFAIL);
+ }
+}
+
+TPM_RESULT VTSP_OIAP(const TCS_CONTEXT_HANDLE hContext,
+ TCS_AUTH *auth) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "OIAP.\n");
+ TPM_RESULT status = TPM_SUCCESS;
+ TPMTRYRETURN( TCSP_OIAP(hContext,
+ &auth->AuthHandle,
+ &auth->NonceEven) );
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ return status;
+}
+
+TPM_RESULT VTSP_OSAP(const TCS_CONTEXT_HANDLE hContext,
+ const TPM_ENTITY_TYPE entityType,
+ const UINT32 entityValue,
+ const TPM_AUTHDATA *usageAuth,
+ TPM_SECRET *sharedSecret,
+ TCS_AUTH *auth) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "OSAP.\n");
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_NONCE nonceEvenOSAP, nonceOddOSAP;
+
+ Crypto_GetRandom((BYTE *) &nonceOddOSAP, sizeof(TPM_NONCE) );
+
+ TPMTRYRETURN( TCSP_OSAP( hContext,
+ entityType,
+ entityValue,
+ nonceOddOSAP,
+ &auth->AuthHandle,
+ &auth->NonceEven,
+ &nonceEvenOSAP) );
+
+ // Calculating Session Secret
+ BYTE sharedSecretText[TPM_DIGEST_SIZE * 2];
+
+ BSG_PackList( sharedSecretText, 2,
+ BSG_TPM_NONCE, &nonceEvenOSAP,
+ BSG_TPM_NONCE, &nonceOddOSAP);
+
+ Crypto_HMAC(sharedSecretText, sizeof(sharedSecretText), (BYTE *) usageAuth, TPM_DIGEST_SIZE, (BYTE *) sharedSecret);
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ return status;
+}
+
+
+
+TPM_RESULT VTSP_ReadPubek( const TCS_CONTEXT_HANDLE hContext,
+ CRYPTO_INFO *crypto_info) {
+
+ TPM_RESULT status;
+ TPM_NONCE antiReplay;
+ TPM_DIGEST checksum;
+ BYTE *pubEKtext;
+ UINT32 pubEKtextsize;
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Reading Public EK.\n");
+
+ // GenerateAuth new nonceOdd
+ Crypto_GetRandom(&antiReplay, sizeof(TPM_NONCE) );
+
+
+ TPMTRYRETURN( TCSP_ReadPubek( hContext,
+ antiReplay,
+ &pubEKtextsize,
+ &pubEKtext,
+ &checksum) );
+
+
+ // Extract the remaining output parameters
+ TPM_PUBKEY pubEK;
+
+ BSG_Unpack(BSG_TPM_PUBKEY, pubEKtext, (BYTE *) &pubEK);
+
+ // Build CryptoInfo for the bindingKey
+ TPM_RSA_KEY_PARMS rsaKeyParms;
+
+ BSG_Unpack(BSG_TPM_RSA_KEY_PARMS,
+ pubEK.algorithmParms.parms,
+ &rsaKeyParms);
+
+ Crypto_RSABuildCryptoInfoPublic(rsaKeyParms.exponentSize,
+ rsaKeyParms.exponent,
+ pubEK.pubKey.keyLength,
+ pubEK.pubKey.key,
+ crypto_info);
+
+ // Destroy rsaKeyParms
+ BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms);
+
+ // Set encryption scheme
+ crypto_info->encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1;
+ //crypto_info->encScheme = pubEK.algorithmParms.encScheme;
+ crypto_info->algorithmID = pubEK.algorithmParms.algorithmID;
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ return status;
+}
+
+TPM_RESULT VTSP_TakeOwnership( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_AUTHDATA *ownerAuth,
+ const TPM_AUTHDATA *srkAuth,
+ CRYPTO_INFO *ek_cryptoInfo,
+ TCS_AUTH *auth) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Taking Ownership of TPM.\n");
+
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_COMMAND_CODE command = TPM_ORD_TakeOwnership;
+ TPM_PROTOCOL_ID proto_id = TPM_PID_OWNER;
+ BYTE *new_srk;
+
+ BYTE *paramText; // Digest to make Auth.
+ UINT32 paramTextSize;
+
+ // vars for srkpubkey parameter
+ TPM_KEY srkPub;
+ TPM_KEY_PARMS srkKeyInfo = {TPM_ALG_RSA, TPM_ES_RSAESOAEP_SHA1_MGF1, TPM_SS_NONE, 12, 0};
+ BYTE srkRSAkeyInfo[12] = { 0x00, 0x00, (RSA_KEY_SIZE >> 8), 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
+ srkKeyInfo.parms = (BYTE *) &srkRSAkeyInfo;
+
+ struct pack_buf_t srkText;
+
+ // GenerateAuth new nonceOdd
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+
+ //These values are accurate for an enc(AuthData).
+ struct pack_buf_t encOwnerAuth, encSrkAuth;
+
+ encOwnerAuth.data = (BYTE *)malloc(sizeof(BYTE) * 256);
+ encSrkAuth.data = (BYTE *)malloc(sizeof(BYTE) * 256);
+
+ if (encOwnerAuth.data == NULL || encSrkAuth.data == NULL) {
+ vtpmloginfo(VTPM_LOG_VTSP, "Could not malloc encrypted auths.\n");
+ status = TPM_RESOURCES;
+ goto abort_egress;
+ }
+
+ Crypto_RSAEnc(ek_cryptoInfo, sizeof(TPM_SECRET), (BYTE *) ownerAuth, &encOwnerAuth.size, encOwnerAuth.data);
+ Crypto_RSAEnc(ek_cryptoInfo, sizeof(TPM_SECRET), (BYTE *) srkAuth, &encSrkAuth.size, encSrkAuth.data);
+
+
+ // Build srk public key struct
+ srkPub.ver = TPM_STRUCT_VER_1_1;
+ srkPub.keyUsage = TPM_KEY_STORAGE;
+ srkPub.keyFlags = 0x00;
+ srkPub.authDataUsage = TPM_AUTH_ALWAYS;
+ memcpy(&srkPub.algorithmParms, &srkKeyInfo, sizeof(TPM_KEY_PARMS));
+ srkPub.PCRInfoSize = 0;
+ srkPub.PCRInfo = 0;
+ srkPub.pubKey.keyLength= 0;
+ srkPub.encDataSize = 0;
+
+ srkText.data = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+ srkText.size = BSG_Pack(BSG_TPM_KEY, (BYTE *) &srkPub, srkText.data);
+
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+
+ paramTextSize = BSG_PackList(paramText, 5,
+ BSG_TPM_COMMAND_CODE,&command,
+ BSG_TPM_PROTOCOL_ID, &proto_id,
+ BSG_TPM_SIZE32_DATA, &encOwnerAuth,
+ BSG_TPM_SIZE32_DATA, &encSrkAuth,
+ BSG_TPM_KEY, &srkPub);
+
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize, ownerAuth, auth) );
+
+ new_srk = srkText.data;
+ TPMTRYRETURN( TCSP_TakeOwnership ( hContext,
+ proto_id,
+ encOwnerAuth.size,
+ encOwnerAuth.data,
+ encSrkAuth.size,
+ encSrkAuth.data,
+ &srkText.size,
+ &new_srk,
+ auth ) );
+
+
+ paramTextSize = BSG_PackList(paramText, 2,
+ BSG_TPM_RESULT, &status,
+ BSG_TPM_COMMAND_CODE, &command);
+ memcpy(paramText + paramTextSize, new_srk, srkText.size);
+ paramTextSize += srkText.size;
+
+
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+ ownerAuth, auth,
+ hContext) );
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ free(srkText.data);
+ free(encSrkAuth.data);
+ free(encOwnerAuth.data);
+ free(paramText);
+
+ TCS_FreeMemory(hContext, new_srk);
+
+ return status;
+}
+
+TPM_RESULT VTSP_DisablePubekRead( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_AUTHDATA *ownerAuth,
+ TCS_AUTH *auth) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Disabling Pubek Read.\n");
+
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_COMMAND_CODE command = TPM_ORD_DisablePubekRead;
+
+ BYTE *paramText; // Digest to make Auth.
+ UINT32 paramTextSize;
+
+ // Generate HMAC
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+
+ paramTextSize = BSG_PackList(paramText, 1,
+ BSG_TPM_COMMAND_CODE, &command);
+
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
+ ownerAuth, auth) );
+
+ // Call TCS
+ TPMTRYRETURN( TCSP_DisablePubekRead ( hContext, // in
+ auth) );
+
+ // Verify Auth
+ paramTextSize = BSG_PackList(paramText, 2,
+ BSG_TPM_RESULT, &status,
+ BSG_TPM_COMMAND_CODE, &command);
+
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+ ownerAuth, auth,
+ hContext) );
+ goto egress;
+
+ abort_egress:
+ egress:
+ free(paramText);
+ return status;
+}
+
+TPM_RESULT VTSP_CreateWrapKey( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_KEY_USAGE usage,
+ const TPM_AUTHDATA *newKeyAuth,
+ const TCS_KEY_HANDLE parentHandle,
+ const TPM_AUTHDATA *osapSharedSecret,
+ buffer_t *pubKeyBuf,
+ TCS_AUTH *auth) {
+
+ int i;
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_COMMAND_CODE command = TPM_ORD_CreateWrapKey;
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Creating new key of type %d.\n", usage);
+
+ // vars for Calculate encUsageAuth
+ BYTE *paramText;
+ UINT32 paramTextSize;
+
+ // vars for Calculate encUsageAuth
+ BYTE XORbuffer[sizeof(TPM_SECRET) + sizeof(TPM_NONCE)];
+ TPM_DIGEST XORKey1;
+ UINT32 XORbufferSize;
+ TPM_SECRET encUsageAuth, encMigrationAuth;
+
+ // vars for Flatten newKey prototype
+ BYTE *flatKey = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+ UINT32 flatKeySize = TCPA_MAX_BUFFER_LENGTH;
+ struct pack_buf_t newKeyText;
+
+ // Fill in newKey
+ TPM_KEY newKey;
+
+ BYTE RSAkeyInfo[12] = { 0x00, 0x00, (RSA_KEY_SIZE >> 8), 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00};
+ newKey.algorithmParms.algorithmID = TPM_ALG_RSA;
+ newKey.algorithmParms.parms = (BYTE *) &RSAkeyInfo;
+ newKey.algorithmParms.parmSize = 12;
+
+ switch (usage) {
+ case TPM_KEY_SIGNING:
+ vtpmloginfo(VTPM_LOG_VTSP, "Creating Signing Key...\n");
+ newKey.keyUsage = TPM_KEY_SIGNING;
+ newKey.algorithmParms.encScheme = TPM_ES_NONE;
+ newKey.algorithmParms.sigScheme = TPM_SS_RSASSAPKCS1v15_SHA1;
+ break;
+ case TPM_KEY_STORAGE:
+ vtpmloginfo(VTPM_LOG_VTSP, "Creating Storage Key...\n");
+ newKey.keyUsage = TPM_KEY_STORAGE;
+ newKey.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1;
+ newKey.algorithmParms.sigScheme = TPM_SS_NONE;
+ break;
+ case TPM_KEY_BIND:
+ vtpmloginfo(VTPM_LOG_VTSP, "Creating Binding Key...\n");
+ newKey.keyUsage = TPM_KEY_BIND;
+ newKey.algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1;
+ newKey.algorithmParms.sigScheme = TPM_SS_NONE;
+ break;
+ default:
+ vtpmloginfo(VTPM_LOG_VTSP, "Cannot create key. Invalid Key Type.\n");
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+
+
+ newKey.ver = TPM_STRUCT_VER_1_1;
+
+ newKey.keyFlags = 0;
+ newKey.authDataUsage = TPM_AUTH_ALWAYS;
+ newKey.pubKey.keyLength= 0;
+ newKey.encDataSize = 0;
+ newKey.encData = NULL;
+
+ // FIXME: Support PCR bindings
+ newKey.PCRInfoSize = 0;
+ newKey.PCRInfo = NULL;
+
+ // Calculate encUsageAuth
+ XORbufferSize = BSG_PackList( XORbuffer, 2,
+ BSG_TPM_SECRET, osapSharedSecret,
+ BSG_TPM_NONCE, &auth->NonceEven);
+ Crypto_SHA1Full(XORbuffer, XORbufferSize, (BYTE *) &XORKey1);
+
+ // FIXME: No support for migratable keys.
+ for (i=0; i < TPM_DIGEST_SIZE; i++)
+ ((BYTE *) &encUsageAuth)[i] = ((BYTE *) &XORKey1)[i] ^ ((BYTE *) newKeyAuth)[i];
+
+ // Flatten newKey prototype
+ flatKeySize = BSG_Pack(BSG_TPM_KEY, (BYTE *) &newKey, flatKey);
+ newKeyText.data = flatKey;
+ newKeyText.size = flatKeySize;
+
+ // GenerateAuth new nonceOdd
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+
+ // Generate HMAC
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+
+ paramTextSize = BSG_PackList(paramText, 3,
+ BSG_TPM_COMMAND_CODE, &command,
+ BSG_TPM_AUTHDATA, &encUsageAuth,
+ BSG_TPM_AUTHDATA, &encMigrationAuth);
+ memcpy(paramText + paramTextSize, newKeyText.data, newKeyText.size);
+ paramTextSize += newKeyText.size;
+
+
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
+ osapSharedSecret, auth) );
+
+ // Call TCS
+ TPMTRYRETURN( TCSP_CreateWrapKey( hContext,
+ parentHandle,
+ encUsageAuth,
+ encMigrationAuth,
+ &newKeyText.size,
+ &newKeyText.data,
+ auth) );
+
+ // Verify Auth
+ paramTextSize = BSG_PackList(paramText, 2,
+ BSG_TPM_RESULT, &status,
+ BSG_TPM_COMMAND_CODE, &command);
+ memcpy(paramText + paramTextSize, newKeyText.data, newKeyText.size);
+ paramTextSize += newKeyText.size;
+
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+ osapSharedSecret, auth, 0) );
+
+ // Unpack/return key structure
+ TPMTRYRETURN(buffer_init(pubKeyBuf, 0, 0) );
+ TPMTRYRETURN(buffer_append_raw(pubKeyBuf, newKeyText.size, newKeyText.data) );
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ free(flatKey);
+ free(paramText);
+ TCS_FreeMemory(hContext, newKeyText.data);
+
+ return status;
+}
+
+TPM_RESULT VTSP_LoadKey(const TCS_CONTEXT_HANDLE hContext,
+ const TCS_KEY_HANDLE hUnwrappingKey,
+ const buffer_t *rgbWrappedKeyBlob,
+ const TPM_AUTHDATA *parentAuth,
+ TPM_HANDLE *newKeyHandle,
+ TCS_AUTH *auth,
+ CRYPTO_INFO *cryptoinfo /*= NULL*/) {
+
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Loading Key.\n%s","");
+
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_COMMAND_CODE command = TPM_ORD_LoadKey;
+
+ BYTE *paramText; // Digest to make Auth.
+ UINT32 paramTextSize;
+
+ if ((rgbWrappedKeyBlob == NULL) || (parentAuth == NULL) ||
+ (newKeyHandle==NULL) || (auth==NULL)) {
+ status = TPM_BAD_PARAMETER;
+ goto abort_egress;
+ }
+
+ // Generate Extra TCS Parameters
+ TPM_HANDLE phKeyHMAC;
+
+ // Generate HMAC
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+
+ paramTextSize = BSG_PackList(paramText, 1,
+ BSG_TPM_COMMAND_CODE, &command);
+
+ memcpy(paramText + paramTextSize, rgbWrappedKeyBlob->bytes, buffer_len(rgbWrappedKeyBlob));
+ paramTextSize += buffer_len(rgbWrappedKeyBlob);
+
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
+ parentAuth, auth) );
+
+ // Call TCS
+ TPMTRYRETURN( TCSP_LoadKeyByBlob( hContext,
+ hUnwrappingKey,
+ buffer_len(rgbWrappedKeyBlob),
+ rgbWrappedKeyBlob->bytes,
+ auth,
+ newKeyHandle,
+ &phKeyHMAC) );
+
+ // Verify Auth
+ paramTextSize = BSG_PackList(paramText, 3,
+ BSG_TPM_RESULT, &status,
+ BSG_TPM_COMMAND_CODE, &command,
+ BSG_TPM_HANDLE, newKeyHandle);
+
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+ parentAuth, auth,
+ hContext) );
+
+ // Unpack/return key structure
+ if (cryptoinfo != NULL) {
+ TPM_KEY newKey;
+
+ BSG_Unpack(BSG_TPM_KEY, rgbWrappedKeyBlob->bytes , &newKey);
+ TPM_RSA_KEY_PARMS rsaKeyParms;
+
+ BSG_Unpack(BSG_TPM_RSA_KEY_PARMS,
+ newKey.algorithmParms.parms,
+ &rsaKeyParms);
+
+ Crypto_RSABuildCryptoInfoPublic(rsaKeyParms.exponentSize,
+ rsaKeyParms.exponent,
+ newKey.pubKey.keyLength,
+ newKey.pubKey.key,
+ cryptoinfo);
+
+ // Destroy rsaKeyParms
+ BSG_Destroy(BSG_TPM_RSA_KEY_PARMS, &rsaKeyParms);
+
+ // Set encryption scheme
+ cryptoinfo->encScheme = CRYPTO_ES_RSAESOAEP_SHA1_MGF1;
+ }
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ free(paramText);
+ return status;
+}
+
+TPM_RESULT VTSP_Unbind( const TCS_CONTEXT_HANDLE hContext,
+ const TPM_KEY_HANDLE key_handle,
+ const buffer_t *bound_data,
+ const TPM_AUTHDATA *usage_auth,
+ buffer_t *clear_data,
+ TCS_AUTH *auth) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Unbinding %d bytes of data.\n", buffer_len(bound_data));
+
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_COMMAND_CODE command = TPM_ORD_UnBind;
+
+ BYTE *paramText; // Digest to make Auth.
+ UINT32 paramTextSize;
+
+ // Generate Extra TCS Parameters
+ struct pack_buf_t clear_data32;
+ BYTE *clear_data_text;
+ UINT32 clear_data_size;
+
+ // Generate HMAC
+ Crypto_GetRandom(&auth->NonceOdd, sizeof(TPM_NONCE) );
+
+ struct pack_buf_t bound_data32 = {bound_data->size, bound_data->bytes};
+
+ paramText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+
+ paramTextSize = BSG_PackList(paramText, 2,
+ BSG_TPM_COMMAND_CODE, &command,
+ BSG_TPM_SIZE32_DATA, &bound_data32);
+
+ TPMTRYRETURN( GenerateAuth( paramText, paramTextSize,
+ usage_auth, auth) );
+
+ // Call TCS
+ TPMTRYRETURN( TCSP_UnBind( hContext,
+ key_handle,
+ buffer_len(bound_data),
+ bound_data->bytes,
+ auth,
+ &clear_data_size,
+ &clear_data_text) );
+
+
+ // Verify Auth
+ clear_data32.size = clear_data_size;
+ clear_data32.data = clear_data_text;
+ paramTextSize = BSG_PackList(paramText, 3,
+ BSG_TPM_RESULT, &status,
+ BSG_TPM_COMMAND_CODE, &command,
+ BSG_TPM_SIZE32_DATA, &clear_data32);
+
+ TPMTRYRETURN( VerifyAuth( paramText, paramTextSize,
+ usage_auth, auth,
+ hContext) );
+
+ // Unpack/return key structure
+ TPMTRYRETURN(buffer_init(clear_data, 0, 0));
+ TPMTRYRETURN(buffer_append_raw (clear_data, clear_data_size, clear_data_text) );
+
+ goto egress;
+
+ abort_egress:
+
+ egress:
+
+ free(paramText);
+ TCS_FreeMemory(hContext, clear_data_text);
+
+ return status;
+}
+
+TPM_RESULT VTSP_Bind( CRYPTO_INFO *cryptoInfo,
+ const buffer_t *inData,
+ buffer_t *outData)
+{
+ vtpmloginfo(VTPM_LOG_VTSP, "Binding %d bytes of data.\n", buffer_len(inData));
+ TPM_BOUND_DATA boundData;
+ UINT32 i;
+
+ // Fill boundData's accessory information
+ boundData.ver = TPM_STRUCT_VER_1_1;
+ boundData.payload = TPM_PT_BIND;
+ boundData.payloadData = inData->bytes;
+
+ // Pack boundData before encryption
+ BYTE* flatBoundData = (BYTE *)malloc(sizeof(BYTE) *
+ (sizeof(TPM_VERSION) +
+ sizeof(TPM_PAYLOAD_TYPE) +
+ buffer_len(inData)));
+ if (flatBoundData == NULL) {
+ return TPM_NOSPACE;
+ }
+ UINT32 flatBoundDataSize = 0;
+ flatBoundDataSize = BSG_PackList( flatBoundData, 2,
+ BSG_TPM_VERSION, &boundData.ver,
+ BSG_TYPE_BYTE, &boundData.payload);
+
+ memcpy(flatBoundData+flatBoundDataSize, inData->bytes, buffer_len(inData));
+ flatBoundDataSize += buffer_len(inData);
+
+ BYTE out_tmp[RSA_KEY_SIZE/8]; // RSAEnc does not do blocking, So this is what will come out.
+ UINT32 out_tmp_size;
+
+ // Encrypt flatBoundData
+ Crypto_RSAEnc( cryptoInfo,
+ flatBoundDataSize,
+ flatBoundData,
+ &out_tmp_size,
+ out_tmp);
+
+ if (out_tmp_size > RSA_KEY_SIZE/8) {
+ // The result of RSAEnc should be a fixed size based on key size.
+ vtpmlogerror(VTPM_LOG_VTSP, "Enc buffer just overflowed.\n");
+ }
+
+ buffer_init(outData, 0, NULL);
+ buffer_append_raw(outData, out_tmp_size, out_tmp);
+
+ vtpmloginfo(VTPM_LOG_TXDATA, "Bind Generated[%d] = 0x", out_tmp_size);
+ for(i = 0 ; i < out_tmp_size ; i++) {
+ vtpmloginfomore(VTPM_LOG_TXDATA, "%2.2x ", out_tmp[i]);
+ }
+ vtpmloginfomore(VTPM_LOG_TXDATA, "\n");
+
+ // Free flatBoundData
+ free(flatBoundData);
+
+ return TPM_SUCCESS;
+}
+
+// Function Reaches into unsupported TCS command, beware.
+TPM_RESULT VTSP_RawTransmit(const TCS_CONTEXT_HANDLE hContext,
+ const buffer_t *inbuf,
+ buffer_t *outbuf ) {
+
+ vtpmloginfo(VTPM_LOG_VTSP, "Passthrough in use.\n");
+ TPM_RESULT status = TPM_SUCCESS;
+
+ // Generate Extra TCS Parameters
+ BYTE *resultText = (BYTE *) malloc(sizeof(BYTE) * TCPA_MAX_BUFFER_LENGTH);
+ UINT32 resultTextSize = TCPA_MAX_BUFFER_LENGTH;
+
+ // Call TCS
+ TPMTRYRETURN( TCSP_RawTransmitData(buffer_len(inbuf), inbuf->bytes,
+ &resultTextSize, resultText) );
+
+ // Unpack/return key structure
+ TPMTRYRETURN(buffer_init (outbuf, resultTextSize, resultText) );
+ goto egress;
+
+ abort_egress:
+
+ egress:
+ TCS_FreeMemory(hContext, resultText);
+ free(resultText);
+ return status;
+}